//
//  Queue.m
//  Wi-Fi Party remade-1
//
//  Created by Vieta Ken on 2021/2/26.
//

#import <Foundation/Foundation.h>
#import "Queue.h"

#define WRITE_BOUNDARY self->last_reader
#define BOUNDARY self->bufferSize

@interface Queue()
@end

@implementation Queue

-(id)init{
    self=[super init];
    self->reader=0;
    self->last_reader=0;
    self->writer=0;
    self->empty=0;
    self->bufferSize=BUFFER_SIZE;
    self->content=malloc(self->bufferSize);
    return self;
}

-(id)init:(int)bufferSize{
    self=[super init];
    self->reader=0;
    self->last_reader=0;
    self->writer=0;
    self->empty=0;
    self->bufferSize=bufferSize;
    self->content=malloc(self->bufferSize);
    return self;
}

-(void)dealloc{
    free(self->content);
}

-(int)rawReadAndWriteTo:(signed char*)dst size:(int)size{
    for(int i=0;i<size;i++){
        if(self->reader==self->writer){
            memset(dst+i, (signed char)0, size-i);
            return i;
        }
        dst[i]=self->content[self->reader];
        self->reader++;
        if(self->reader>=BOUNDARY) self->reader=0;
    }
    return size;
}

-(int)readAndWriteTo:(signed char *)dst size:(int)size{
    if([self canRead]){
        self->last_reader=self->reader;
        self->last_read_size=size;
        return [self rawReadAndWriteTo:dst size:size];
    }else{
        self->empty++;
        self->reader=self->last_reader;
        return [self rawReadAndWriteTo:dst size:size];
    }
}

-(void)writeData:(const signed char*)src size:(int)size{
    for(int i=0;i<size;i++){
        if(self->writer+1==WRITE_BOUNDARY){
            break;
        }
        self->content[self->writer]=src[i];
        self->writer++;
        if(self->writer>=BOUNDARY){
            if(WRITE_BOUNDARY>0) self->writer=0;
            else{
                self->writer--;
                break;
            }
        }
    }
    self->empty=0;
}

-(int)canRead{
    if(WRITE_BOUNDARY<=self->writer){
        return self->writer-WRITE_BOUNDARY;
    }else{
        return self->writer+BOUNDARY-WRITE_BOUNDARY;
    }
}

-(int)canWrite{
    if(WRITE_BOUNDARY<=self->writer){
        return WRITE_BOUNDARY-1+BOUNDARY-self->writer;
    }else{
        return WRITE_BOUNDARY-self->writer-1;
    }
}

@end
